<?php

// +----------------------------------------------------------------------
// | 版权所有 2017-2027 云南环拓科技有限公司，并保留所有权利。
// +----------------------------------------------------------------------
// | Copyright (c) 2017-2027 http://www.yn123.com All rights reserved.
// +----------------------------------------------------------------------
// | Notice: This code is not open source, it is strictly prohibited
// |         to distribute the copy, otherwise it will pursue its
// |         legal responsibility.
// | 注意：  这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用,
// |        不允许对程序代码以任何形式任何目的的再发布。
// +----------------------------------------------------------------------
// | Author: feraner <feraner@163.com> 
// | Date: 2019/11/15
// +----------------------------------------------------------------------

namespace app\common\services;
use app\common\constants\ApiConstant;
use app\common\facade\Arr;
use app\common\facade\TransItem;
use app\common\services\statistics\BehaviorHandleService;
use app\common\services\wechattemplate\JobTemplateService;
use library\tools\Data;
use think\Db;

/**
 * 申请兼职等服务类
 * Class JobOptionService
 * @package app\common\services
 * @author feraner<feraner@163.com>
 * @date 2019/11/15
 */
class JobOptionService
{

    protected $userService = null;

    public function __construct()
    {
        $this->userService = new UserService();
    }

    /**
     * 用户申请该项兼职工作
     *
     * @param $jobId
     * @param $userId
     *
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \Exception
     */
    public function userApplyJob($jobId, $userId)
    {
        $jobInfo = (new JobService())->jobDetail($jobId);
        if ($jobInfo) {
            $userInfo = $this->userService->userInfo($userId, ['extend']);
            try {
                Db::startTrans();
                $this->__beforeUserApplyJob($jobInfo, $userInfo);

                $result = $this->__applyJobHandle($jobInfo, $userInfo);

                if ($result) {
                    $this->__afterUserApplyJob($jobInfo, $userInfo);
                }
                Db::commit();
                return true;
            } catch (\Exception $e) {
                Db::rollback();
                throw $e;
            }
        }
        throw new \Exception(
            ApiConstant::JOB_NOT_FUND_ERROR_STR,
            ApiConstant::JOB_NOT_FUND_ERROR
        );
    }


    /**
     * 用户报名前检测
     * @param $jobInfo
     * @param $userId
     *
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \Exception
     */
    private function __beforeUserApplyJob($jobInfo, $userInfo)
    {
        //1: 用户是否完善了信息
        if (!$this->userService->checkUserInfoIsDone($userInfo)) {
            throw  new \Exception(
                ApiConstant::USER_INFO_NOT_DONE_STR,
                ApiConstant::USER_INFO_NOT_DONE
            );
        }

        //2: 检测是否已经报名
        $hadApply = $this->checkUserApply(Arr::get($userInfo, 'id'), Arr::get($jobInfo, 'id'));
        if ($hadApply) {
            throw new \Exception(
                ApiConstant::JOB_APPLY_AGAIN_ERROR_STR,
                ApiConstant::JOB_APPLY_AGAIN_ERROR
            );
        }

        //3: 检测兼职是否还能报名

    }


    /**
     * 处理报名兼职
     * @param $jobInfo
     * @param $userInfo
     *
     * @return int|string
     * @throws \think\Exception
     * @throws \think\exception\PDOException
     */
    private function __applyJobHandle($jobInfo, $userInfo)
    {
        $result = Db::name('jobs_apply')
            ->insertGetId([
                'job_id'            => Arr::get($jobInfo, 'id'),
                'publisher_id'      => Arr::get($jobInfo, 'user_id', 0),
                'user_id'           => Arr::get($userInfo, 'id'),
                'status'            => 1,
                'created_at'        => time(),
                'updated_at'        => time()
            ]);
        if ($result) {
            $result = Db::name('jobs')
                ->where('id', Arr::get($jobInfo, 'id'))
                ->update([
                    'had_worker'    => Db::raw('had_worker + 1'),
                    'updated_at'    => time()
                ]);
        }
        return $result;
    }


    /**
     * 报名兼职以后处理
     * @param $jobInfo
     * @param $userInfo
     */
    private function __afterUserApplyJob($jobInfo, $userInfo)
    {

        //发送消息给发布人
        (new JobTemplateService())->sendUserApplyJob($jobInfo, $userInfo);
    }



    /**
     * 检测用户是否报名了该兼职
     * @param $userId
     * @param $jobId
     *
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function checkUserApply($userId, $jobId)
    {
        $hadApply = Db::name('jobs_apply')
            ->where('job_id', $jobId)
            ->where('user_id', $userId)
            ->find() ?: false;
        return $hadApply;
    }


    /**
     * 审核报名兼职的用户
     * @param $postData
     *
     * @return bool|int|string
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function auditUserApplyJob($postData)
    {   

        $result = false;
        $applyInfo = Db::name('jobs_apply')
            ->where('id', Arr::get($postData, 'applyId'))
            ->find() ?: [];
        $userInfo = (new UserService())->userInfo(Arr::get($applyInfo, 'user_id'));
        if ($applyInfo && $userInfo) {
            $jobInfo = Db::name('jobs')
                ->where('id', Arr::get($postData, 'jobId'))
                ->find() ?: [];
            if ($jobInfo['need_worker'] > $jobInfo['check_worker']) {
                try{
                    Db::startTrans();
                    //1: 修改报名状态
                    $result = Db::name('jobs_apply')
                        ->where('id', Arr::get($applyInfo, 'id'))
                        ->where('user_id', Arr::get($userInfo, 'id'))
                        ->update([
                            'status'        => Arr::get($postData, 'status'),
                            'replay'        => Arr::get($postData, 'message'),
                            'updated_at'    => time()
                        ]);
                    if ($result) {
                        if (Arr::valueEq($postData, 'status', 2)) {
                            //审核通过
                            //2:修改兼职 已审核到人数
                            $result = Db::name('jobs')
                                ->where('id', Arr::get($postData, 'jobId'))
                                ->update([
                                    'updated_at'        => time(),
                                    'check_worker'      => Db::raw('check_worker + 1')
                                ]);
                            //3：审核通过 发送微信模版消息给用户
                            (new JobTemplateService())->sendCheckJobPass($jobInfo, $applyInfo);
                            if ($jobInfo['need_worker'] == $jobInfo['check_worker'] + 1) {
                                //报名人生已满 发送消息给发布人
                                (new JobTemplateService())->sendPublishUserJobWorkerIsOk($jobInfo);

                            }
                        } else {
                            //审核失败 发送微信模版消息给用户
                            (new JobTemplateService())->sendCheckJobNoPass($jobInfo, $applyInfo, $postData);
                        }
                    }
                    if ($result) {
                        Db::commit();
                    } else {
                        Db::rollback();
                        throw new \Exception('审核失败!');
                    }
                } catch (\Exception $e) {
                    Db::rollback();
                    throw $e;
                }
            } else {
                throw new \Exception('人员已经满！');
            }
        }
        return $result;
    }


    /**
     * 用户取消申请到兼职
     * @param        $applyJobInfo
     * @param string $msg
     *
     * @return bool|int|string
     * @throws \Exception
     */
    public function cancelApplyJob($applyJobInfo, $msg = '')
    {
        $result = false;
        try {
            Db::startTrans();
            //1: 修改申请表状态
            $result = Db::name('jobs_apply')
                ->where('id', Arr::get($applyJobInfo, 'id'))
                ->update([
                    'status'        => 6,
                    'updated_at'    => time(),
                    'cancel'        => $msg
                ]);
            if ($result) {
                //2: 修改申请人数
                $updateData = [
                    'updated_at'        => time(),
                    'had_worker'        => Db::raw('had_worker - 1'),
                ];
                if (Arr::valueEq($applyJobInfo, 'status', 2)) {
                    $updateData['check_worker'] = Db::raw('check_worker - 1');
                }
                $result = Db::name('jobs')
                    ->where('id', Arr::get($applyJobInfo, 'job_id'))
                    ->where('is_deleted', 0)
                    ->update($updateData);
            }
            if ($result && Arr::valueEq($applyJobInfo, 'status', 2)) {
                //减少用户信用分
                $result = Db::name('user_extend')
                    ->where('user_id', Arr::get($applyJobInfo, 'user_id'))
                    ->update([
                        'updated_at'    => time(),
                        'credit_score'  => Db::raw('credit_score - ' . sysconf('user_cancel_job_reduce_credit'))
                    ]);

                if($result){
                    //信用分记录
                    Db::name('user_score_log')
                        ->insert([
                            'user_id'           => Arr::get($applyJobInfo, 'user_id'),
                            'credit_score'      => sysconf('user_cancel_job_reduce_credit'),
                            'type'              => 2,
                            'kind'              => 1,
                            'created_at'        => time(),
                            'updated_at'        => time()
                        ]);
                }

               
            }
            if (!$result) {
                Db::rollback();
                throw new \Exception('取消兼职失败！');
            }
            Db::commit();

            //发送取消信息给兼职发布人
            (new JobTemplateService())->sendUserCancelApplyJob($applyJobInfo, $msg);
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
        return $result;
    }


    /**
     * 发布人结算招聘 -- 不在接受申请兼职
     * @param      $jobInfo
     * @param int  $publishUserId
     * @param bool $isAdmin
     *
     * @return bool|int|string
     * @throws \Exception
     */
    public function closeApplyJob($jobInfo, $publishUserId = 0, $isAdmin = false)
    {
        $result = false;
        try {
            Db::startTrans();

            //1: 修改兼职状态
            $result = Db::name('jobs')
                ->where('id', Arr::get($jobInfo, 'id'))
                ->where('status', 2)
                ->where('is_deleted', 0)
                ->update([
                    'status'            => 4,
                    'updated_at'        => time()
                ]);
            if (!$isAdmin && $result) {
                //2: 处理锁定的发布豆
                $needBean = (new PublishJobComputerService())->needBean($jobInfo);
                $checkWorkerNum = Arr::get($jobInfo, 'check_worker', 0);
                //返还的发布豆
                $backBean = 0;
                //返回的积分
                $backCredits = 0;
                if (Arr::get($jobInfo, 'need_worker') > $checkWorkerNum) {
                    $clockBean = $checkWorkerNum * Arr::get($needBean, 'addOneNeedBean', 0);
                    $backBean = Arr::get($needBean, 'needBean') - Arr::get($needBean, 'baseBean') - $clockBean;
                    $backCredits = $backBean * Arr::get($needBean, 'oneBeanGiveCredits', 0);
                } else {
                    $clockBean = Arr::get($needBean, 'needBean', 0) - Arr::get($needBean, 'baseBean', 0);
                }
                $clockCredits = $clockBean * Arr::get($needBean, 'oneBeanGiveCredits', 0);
                $result = Db::name('user_wallet')
                    ->where('user_id', $publishUserId)
                    ->update([
                        'updated_at'        => time(),
                        'publish_bean'      => Db::raw('publish_bean + ' . $backBean),
                        'clock_publish_bean'=> Db::raw('clock_publish_bean - ' . ($clockBean + $backBean)),
                        'used_publish_bean' => Db::raw('used_publish_bean + ' . $clockBean),
                        'credits'           => Db::raw('credits + ' . $clockCredits),
                        'clock_credits'     => Db::raw('clock_credits - ' . ($clockCredits - $backCredits)),
                    ]);
                if ($result) {
                    //3: 发布豆 + 积分 log记录
                    if ($clockBean) {
                        Db::name('user_recharge_log')
                            ->insertGetId([
                                'user_id'           => $publishUserId,
                                'recharge_money'    => 0,
                                'type'              => 2,
                                'publish_bean'      => $clockBean,
                                'kind'              => 1,
                                'created_at'        => time(),
                                'updated_at'        => time()
                            ]);
                    }
                    if ($clockCredits) {
                        Db::name('user_credits_log')
                            ->insertGetId([
                                'user_id'           => $publishUserId,
                                'credits'           => $clockCredits,
                                'type'              => 1,
                                'kind'              => 1,
                                'created_at'        => time(),
                                'updated_at'        => time()
                            ]);
                    }
                }

            }
            if (!$result) {
                throw new \Exception('处理失败！');
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
        return $result;
    }


    /**
     * 完成兼职 - 结算
     * @param $jobInfo
     *
     * @return int|string
     * @throws \Exception
     */
    public function doneJob($jobInfo)
    {
        try {
            Db::startTrans();
            //1: 修改兼职状态
            $result = Db::name('jobs')
                ->where('id', Arr::get($jobInfo, 'id'))
                ->where('status', 4)
                ->where('is_deleted', 0)
                ->update([
                    'status'            => 5,
                    'updated_at'        => time()
                ]);
            if ($result) {
                //2: 修改兼职人员 积分获取情况
                $userJoinGetCredit = sysconf('user_join_get_credit');
                if ($userJoinGetCredit) {
                    $joinJobList = Db::name('jobs_apply')
                        ->where('job_id', Arr::get($jobInfo, 'id'))
                        ->where('status', 4)
                        ->select() ?: [];
                    if ($joinJobList) {
                        foreach ($joinJobList as $oneApply) {
                            if ($userJoinGetCredit) {
                                $result = Db::name('user_wallet')->where('user_id', Arr::get($oneApply, 'user_id'))
                                    ->update([
                                        'credits'   => Db::raw('credits + ' . $userJoinGetCredit),
                                        'updated_at' => time()
                                    ]);
                                if (!$result) {
                                    throw new \Exception('添加积分失败！');
                                }
                                Data::save(
                                    'user_credits_log',
                                    [

                                        'user_id'       => Arr::get($oneApply, 'user_id', 0),
                                        'credits'       => $userJoinGetCredit,
                                        'type'          => 1,
                                        'kind'          => 4,
                                    ]
                                );
                            }
                        }

                        $result = Db::name('jobs_apply')
                            ->where('job_id', Arr::get($jobInfo, 'id'))
                            ->where('status', 4)
                            ->update([
                                'updated_at'        => time(),
                                'status'            => 5
                            ]);
                        if (!$result) {
                            throw new \Exception('修改用户申请状态失败！');
                        }
                    }
                }
                Db::commit();
            }
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
        return $result;
    }


    /**
     * 删除兼职 -- 发布人取消该兼职获得
     * @param $jobInfo
     * @param $publishUserId
     *
     * @return int|string
     * @throws \Exception
     */
    public function deleteJob($jobInfo, $publishUserId)
    {
        try {
            Db::startTrans();

            //1: 修改兼职状态
            $result = Db::name('jobs')
                ->where('id', Arr::get($jobInfo, 'id'))
                ->update([
                    'is_deleted'        => 1,
                    'status'            => 6,
                    'updated_at'        => time()
                ]);
            if ($result) {
                //2: 修改用户参与状态
                $result = Db::name('jobs_apply')
                    ->where('job_id', Arr::get($jobInfo, 'id'))
                    ->where('status', 'IN', [1,2])
                    ->update([
                        'status'        => 7,
                        'updated_at'    => time(),
                        'cancel'        => TransItem::transJobApply(7)
                    ]);

                //3: 退回锁定的发布豆+积分
                if ($result) {
                    $needBean = (new PublishJobComputerService())->needBean($jobInfo);
                    $backBean = Arr::get($needBean, 'needBean', 0) - Arr::get($needBean, 'baseBean', 0);
                    $result = Db::name('user_wallet')
                        ->where('user_id', $publishUserId)
                        ->update([
                            'updated_at'        => time(),
                            'publish_bean'      => Db::raw('publish_bean + ' . $backBean),
                            'clock_publish_bean'=> Db::raw('clock_publish_bean - ' . $backBean),
                            'clock_credits'     => Db::raw('clock_credits - ' .
                                ($backBean * Arr::get($needBean, 'oneBeanGiveCredits', 0))),
                        ]);
                    if (!$result) {
                        throw new \Exception('返还积分失败!');
                    }
                } else {
                    throw new \Exception('修改报名人员状态失败！');
                }

            } else {
                throw new \Exception('删除兼职失败！');
            }
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }

        return $result;
    }


    /**
     * 用户前端消耗发布豆置顶兼职
     * @param $jobId
     * @param $publishId
     *
     * @return bool|int|string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function setJobTop($jobId, $publishId)
    {
        $result = false;
        $jobInfo = Db::name('jobs')
            ->where('id', $jobId)
            ->where('user_id', $publishId)
            ->where('is_top', 0)
            ->where('is_deleted', 0)
            ->where('status', 2)
            ->field('id,user_id,is_top,provinces_id,city_id,county_id')
            ->find() ?: [];
        if ($jobInfo) {
            Db::startTrans();
            try {
                $agentInfo = Db::name('system_agent_user')
                    ->where('pid', 0)
                    ->where('provinces_id', Arr::get($jobInfo, 'provinces_id'))
                    ->where('city_id', Arr::get($jobInfo, 'city_id'))
                    ->where('is_deleted', 0)
                    ->where('status', 1)
                    ->find() ?: [];
                if ($agentInfo) {
                    //1:获取置顶需要的发布豆
                    $needBean = Db::name('bean')
                        ->where('aid', Arr::get($agentInfo, 'id'))
                        ->field('id,aid,job_top')
                        ->find() ?: [];
                    //2:获取用户钱包里面有的豆
                    $userWalletInfo = Db::name('user_wallet')
                        ->where('user_id', $publishId)
                        ->field('id,user_id,publish_bean')
                        ->find() ?: [];
                    if (Arr::get($userWalletInfo, 'publish_bean', 0) >= Arr::get($needBean, 'job_top', 0)) {
                        if (Arr::get($needBean, 'job_top', 0)) {
                            //消耗一个发布豆送几个积分
                            $usedBeanGiveCredits = sysconf('used_bean_give_credits') ?: 0;
                            $giveCredits = ($usedBeanGiveCredits * Arr::get($needBean, 'job_top', 0));
                            //3: 扣除发布豆 + 增加记录
                            $result = Db::name('user_wallet')
                                ->where('user_id', $publishId)
                                ->update([
                                    'updated_at'        => time(),
                                    'publish_bean'      => Db::raw('publish_bean - ' . Arr::get($needBean, 'job_top', 0)),
                                    'credits'           => Db::raw('credits + '  . $giveCredits)
                                ]);
                            if ($result) {
                                //豆记录
                                Db::name('user_recharge_log')->insertGetId([
                                    'user_id'           => $publishId,
                                    'publish_bean'      => Arr::get($needBean, 'job_top', 0),
                                    'type'              => 2,
                                    'kind'              => 5,
                                    'created_at'        => time(),
                                    'updated_at'        => time()
                                ]);
                                if ($giveCredits) {
                                    //积分记录
                                    Db::name('user_credits_log')->insertGetId([
                                        'user_id'       => $publishId,
                                        'credits'       => $giveCredits,
                                        'type'          => 1,
                                        'kind'          => 6,
                                        'created_at'    => time(),
                                        'updated_at'    => time()
                                    ]);
                                }
                            } else {
                                throw new \Exception('置顶资源扣除失败！');
                            }

                        }
                        //4: 设置兼职的置顶状态
                        $result = Db::name('jobs')
                            ->where('id', Arr::get($jobInfo, 'id'))
                            ->update([
                                'is_top'        => 1,
                                'updated_at'    => time()
                            ]);
                        Db::commit();
                    } else {
                        throw new \Exception(
                            ApiConstant::JOB_PUBLISH_NOT_ENOUGH_BEAN_STR,
                            ApiConstant::JOB_PUBLISH_NOT_ENOUGH_BEAN
                        );
                    }
                }
            } catch (\Exception $e) {
                Db::rollback();
                throw $e;
            }
        }

        return $result;
    }



}
